﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using intera = System.Windows.Interactivity;
using System.Reflection;
using MoneyBook.Assets.Resources;
using System.Windows.Controls.Primitives;
using System.Windows.Markup;
using System.Collections.Generic;
using MoneyBook.ComponentModel;
using MoneyBook.Web.Assets.Resources;

namespace MoneyBook.Interactivity {

    [intera.DefaultTrigger(typeof(UIElement), typeof(System.Windows.Interactivity.EventTrigger), "MouseLeftButtonDown")]
    [intera.DefaultTrigger(typeof(ButtonBase), typeof(System.Windows.Interactivity.EventTrigger), "Click")]
    [intera.DefaultTrigger(typeof(Selector), typeof(System.Windows.Interactivity.EventTrigger), "SelectionChanged")]
    [ContentProperty("Parameters")]
    public class InvokeMethodAction : intera.TargetedTriggerAction<object>, INotifyActionCompleted {

        public InvokeMethodAction() {
            this.Parameters = new ParameterCollection();
        }

        public event EventHandler<ActionCompletedEventArgs> ActionCompleted;

        public string MethodName { get; set; }

        //public ParameterCollection Parameters {get; private set;}

        public ParameterCollection Parameters {
            get { return (ParameterCollection)GetValue(ParametersProperty); }
            set { SetValue(ParametersProperty, value); }
        }

        public static readonly DependencyProperty ParametersProperty =
            DependencyProperty.Register("Parameters", typeof(ParameterCollection), typeof(InvokeMethodAction), new PropertyMetadata(OnParametersChanged));

        private static void OnParametersChanged(object sender, DependencyPropertyChangedEventArgs e) {

        }

        protected override void Invoke(object parameter) {
            if (this.Target == null || string.IsNullOrWhiteSpace(this.MethodName)) {
                return;
            }
            Type targetType = this.Target.GetType();
            
            //TODO:最適なメソッドの検索
            MethodInfo method = targetType.GetMethod(this.MethodName, BindingFlags.Public | BindingFlags.Instance);
            if (method == null) {
                throw new InvalidOperationException(String.Format(ExceptionMessages.TargetMethodNotFound, this.MethodName));
            }
            List<object> invokeParams = new List<object>();
            if (this.Parameters != null && this.Parameters.Count > 0) {
                ParameterInfo[] methodParams = method.GetParameters();
                if (this.Parameters.Count != methodParams.Length) {
                    throw new InvalidOperationException("Not matched parameter length " + this.MethodName);
                }
                int i = 0;
                foreach (object invokeParam in this.Parameters.GetParameterValues(parameter)) {
                    invokeParams.Add(TypeConverterHelper.ConvertToType(invokeParam, methodParams[i++].ParameterType));
                }
            }

            object result = method.Invoke(this.Target, invokeParams.ToArray());
            if (this.ActionCompleted != null) {
                this.ActionCompleted(this, new ActionCompletedEventArgs(result));
            }
        }
    }
}
